<?php
require_once 'vendor/autoload.php';
use \Firebase\JWT\JWT;
use Firebase\JWT\Key;

class BaseController extends Controller{
	public $layout = "layout.html";
	public $uid;
	public $token;
	function __construct()
	{
		parent::__construct();
	}

	

	function init(){
		header("Content-type: text/html; charset=utf-8");
		require(APP_DIR.'/protected/include/functions.php');	
		$__controller = isset($_REQUEST['c']) ? strtolower($_REQUEST['c']) : 'main';
		$__action     = isset($_REQUEST['a']) ? strtolower($_REQUEST['a']) : 'index';
		
		$this->_controller = $__controller;
		$this->_action = $__action;
		//diy end---------------------
	}

	/**
     * 从Token中解析用户ID
     */
    public function getLoginUserId(){
        try {
            $this->token = getToken();
            if (empty($this->token)) {
                throw new Exception('Token为空');
            }
            $secretKey = $GLOBALS['JWT_SECRET_KEY'];
            $key = new Key($secretKey , 'HS256');
            $decoded = JWT::decode($this->token, $key);
            $userId = $decoded->userId;
            return $userId;
        } catch (Exception $e) {
            return false;
        }
    }

    function tips($msg, $url){
    	$url = "location.href=\"{$url}\";";
		echo "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><script>function sptips(){alert(\"{$msg}\");{$url}}</script></head><body onload=\"sptips()\"></body></html>";
		exit;
    }
    function jump($url, $delay = 0){
        echo "<html><head><meta http-equiv='refresh' content='{$delay};url={$url}'></head><body></body></html>";
        exit;
	}
	
	/**
	 * 写log
	 * @param $level ERROR\WARN\NOTICE\INFO\DEBUG
	 * @param $msg 日志内容
	 */
	function wlog($level,$msg){
		$this->slog = new spLog();
		$this->slog->log($msg,$level);
	}
	
	/**
     * 接口签名鉴权
     */
    private function auth() {
        // 获取请求参数（支持GET和POST）
        $params = $_GET;
        if (!empty($_POST)) {
            $params = array_merge($params, $_POST);
        }
        
        // 验证必要参数
        $required = ['app_id', 'timestamp', 'nonce', 'signature'];
        foreach ($required as $field) {
            if (!isset($params[$field]) || empty($params[$field])) {
				error("缺少必要参数：{$field}");
            }
        }
        
        // 验证时间戳有效期（5分钟内）
        $now = time();
        if (abs($now - $params['timestamp']) > 300) {
			error("请求已过期，请重新发起");
        }
        
        // 验证nonce唯一性（防止重放攻击，可根据实际情况用Redis存储）
        if (!$this->checkNonce($params['nonce'], $params['app_id'])) {
			error("无效的随机数");
        }
        
        // 查询渠道信息
        $channel = $this->getChannelInfo($params['app_id']);
        if (!$channel) {
			error("渠道不存在或已禁用");
        }
        
        // 生成签名并验证
        $sign = $this->generateSign($params, $channel['channel_secret']);
        if ($sign !== $params['signature']) {
			error("签名验证失败");
        }
    }
    
    /**
     * 获取渠道信息
     * @param string $channelId
     * @return array|bool
     */
    private function getChannelInfo($channelId) {
        // 这里假设使用PDO连接数据库，实际请根据项目数据库配置修改
        $channel = new OpenChannel();
        $result = $channel->find(['app_id'=>$channelId,"status"=>1]);
        if(!$result){
            return false;
        }
        return $result;
    }
    
    /**
     * 验证nonce唯一性
     * @param string $nonce
     * @param string $channelId
     * @return bool
     */
    private function checkNonce($nonce, $channelId) {
        // 实际项目中建议用Redis存储已使用的nonce，设置5分钟过期时间
        // 这里仅为示例，实际需实现存储逻辑
        $redis = new ZDRedis();
        $key = "api_nonce:{$channelId}:{$nonce}";
        if ($redis->isExists($key)) {
            return false;
        }
        $redis->set($key, "nonce", 300); // 5分钟过期
        return true;
    }
    
    /**
     * 生成签名
     * @param array $params
     * @param string $appSecret
     * @return string
     */
    private function generateSign($params, $appSecret) {
        // 去除签名参数
        unset($params['signature']);
        // 按字典序排序
        ksort($params);
        // 拼接字符串
        $string = '';
        foreach ($params as $k => $v) {
            $string .= "{$k}={$v}&";
        }
        // 拼接密钥
        $string .= "app_secret={$appSecret}";
        // 生成MD5签名（实际项目可根据需求使用sha256等算法）
        return md5($string);
    }
} 